#ifndef MEASURE_SIZE_TRACKER_GEOMETRY_ELEMENTS_H_
#define MEASURE_SIZE_TRACKER_GEOMETRY_ELEMENTS_H_

#if defined(_MSC_VER)
#pragma once
#endif

#include "fast_trigonometries.h"
#include "point_2.h"
#include "box_2.h"
#include "segment_2.h"
#include "angle_box_2.h"
#include "ring_2.h"
#include "arc_2.h"
#include "annulus_2.h"
#include "annulus_arc_2.h"
#include "polygon_2.h"

#include <boost/assert.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/math/special_functions/round.hpp>

class size_2 {
public:
  size_2(void) : sx(0), sy(0) {}
  size_2(double sxval, double syval) : sx(sxval), sy(syval) {}

  size_2(const size_2& right_value)
  { 
    if (this != &right_value) {
      sx = right_value.sx;
      sy = right_value.sy;
    }
  }

  size_2& operator=(const size_2& right_value)
  {
    if (this != &right_value) {
      sx = right_value.sx;
      sy = right_value.sy;
    }

    return *this;
  }

public:
  bool operator==(const size_2& right_operand) const
  {
    return (sx==right_operand.sx && sy==right_operand.sy);
  }

  bool operator!=(const size_2& right_operand) const
  {
    return !(*this==right_operand);
  }

  bool operator<(const size_2& right_operand) const
  {
    return (sx<right_operand.sx || sy<right_operand.sy);
  }

  bool operator>(const size_2& right_operand) const
  {
    return (sx>right_operand.sx && sy>right_operand.sy)  ||
      (sx>right_operand.sx && sy==right_operand.sy) ||
      (sx==right_operand.sx && sy>right_operand.sy);
  }

public:
  double sx;
  double sy;
};

typedef boost::mpl::vector<point_2, segment_2, box_2, angle_box_2> shapes_i;
typedef boost::mpl::push_back<shapes_i, ring_2>::type shapes_ii;
typedef boost::mpl::push_back<shapes_ii, arc_2>::type shapes_iii;
typedef boost::mpl::push_back<shapes_iii, annulus_2>::type shapes_iv;
typedef boost::mpl::push_back<shapes_iv, annulus_arc_2>::type shapes_v;
typedef boost::mpl::push_back<shapes_v, polygon_2>::type shape_types;
typedef boost::make_variant_over<shape_types>::type shape_2;
#endif // MEASURE_SIZE_TRACKER_GEOMETRY_ELEMENTS_H_